﻿#pragma once

#include <QObject>
#include <QGraphicsItem>
#include <QGraphicsView>
#include <QMouseEvent>
#include <QImage>
#include <QWheelEvent>
#include <QGraphicsScene>
#include <QGraphicsSceneWheelEvent>
#include <QScrollBar>
#include <QOpenGLWidget>

#include "qt_graphis_pixmap.h"

class QtQGraphicsView :  public QGraphicsView
{
    Q_OBJECT;
signals:
    void sendPosition(QPointF pos);
public:
    QGraphicsScene* m_scene= nullptr;
    QMatrix m_qmatrix;
    double m_scale = 1;
    double m_ratio = 1.1;
    double m_scale_min = 1;
    double m_scale_max = 1;

    QtQGraphicsPixmapItem* m_pixmapItem=nullptr;

    explicit QtQGraphicsView(QWidget* parent)
    :QGraphicsView(parent)
    {
        setViewport(new QOpenGLWidget());
        setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
        m_scene = new QGraphicsScene();
        m_scene->setItemIndexMethod(QGraphicsScene::NoIndex);
        this->setScene(m_scene);
        m_pixmapItem = new QtQGraphicsPixmapItem();
        m_pixmapItem->setAcceptHoverEvents(true);
        m_scene->addItem(m_pixmapItem);
        connect(m_pixmapItem, &QtQGraphicsPixmapItem::sendMessage, this, &QtQGraphicsView::receiveMessage);
    }
    virtual void wheelEvent(QWheelEvent* event)
    {
        QPointF cursorPoint = event->pos();
        QPointF scenePos = this->mapToScene(QPoint(cursorPoint.x(), cursorPoint.y()));
        qreal viewWidth = this->viewport()->width();
        qreal viewHeight = this->viewport()->height();

        qreal hScale = cursorPoint.x() / viewWidth;
        qreal vScale = cursorPoint.y() / viewHeight;

        {
            int wheelDeltaValue = event->delta();
            if (wheelDeltaValue > 0)
            {//    Ϲ      Ŵ ;
                double value = m_scale * m_ratio;
                m_scale = value;
                m_qmatrix.setMatrix(m_scale, this->matrix().m12(), this->matrix().m21(), m_scale, this->matrix().dx(), this->matrix().dy());
                this->setMatrix(m_qmatrix, false);
            }
            else
            {
                double value = m_scale / m_ratio;
                if (value >= m_scale_min)
                {
                    m_scale = value;
                    m_qmatrix.setMatrix(m_scale, this->matrix().m12(), this->matrix().m21(), m_scale, this->matrix().dx(), this->matrix().dy());
                    this->setMatrix(m_qmatrix, false);
                }

            }
            QPointF viewPoint = this->matrix().map(scenePos);
            horizontalScrollBar()->setValue(int(viewPoint.x() - viewWidth * hScale));
            verticalScrollBar()->setValue(int(viewPoint.y() - viewHeight * vScale));

        }
    }

    void receiveMessage(QPointF pos,QString message)
    {
        emit sendPosition(pos);
    }

    void setViewScale(int width, int height)
    {
        double ratiox = double(this->width()) / double(width);
        double ratioy = double(this->height()) / double(height);
        double ratio_image = ratiox < ratioy ? ratiox : ratioy;

        this->m_scale_min = ratio_image;
        this->m_scale = ratio_image;
        QMatrix q;
        q.setMatrix(m_scale, matrix().m12(), matrix().m21(), m_scale, matrix().dx(), matrix().dy());
        setMatrix(q, false);
        return;
    }

    void setImage(QImage image,QString message)
    {
        if (!image.isNull())
        {
            QTextOption toption(Qt::AlignLeft | Qt::AlignTop);//Qt::AlignLeft | Qt::AlignVCenter | Qt::TextWrapAnywhere,
            toption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
            QFont font("Arial", 50); // 设置字体和大小
            QPainter painter(&image);
            if (image.rect().isValid() && !message.isEmpty())
            {
                painter.setPen(Qt::darkCyan);
                painter.setFont(font);
                painter.drawText(image.rect(), message);
            }

            m_pixmapItem->setPixmap(QPixmap::fromImage(image));

            m_pixmapItem->initMask(image.size());


            m_pixmapItem->setScale(1);
            QRectF qrectf = m_pixmapItem->boundingRect();
            m_scene->setSceneRect(qrectf);
            setViewScale(image.width(), image.height());

        }
        return;
    }
};
